package com.haohuo.importer;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.haohuo.config.interfaces.ImportTask;
import com.haohuo.utils.ComResult;
import com.haohuo.utils.DateUtil;
import com.haohuo.utils.RetCode;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.net.URL;
import java.util.List;

import static com.haohuo.utils.ComResult.error;
import static com.haohuo.utils.ComResult.success;

public abstract class AbstractImportService<
        S extends ServiceImpl<? extends BaseMapper<E>,E>,
        E extends ImportTask,
        DTO> implements IImportService<DTO> {
    @Autowired
    S sysImportTaskService;

    /**
     * 需要任务接口具体实现类，用来创建对象。
     * @return
     */
    protected abstract Class<E> getClazz() throws Exception;

    /**
     * 处理业务逻辑
     * 这里不要忘记修改SysImportTask表的记录状态
     * @param obj
     * @param importTask
     * @return
     */
    protected abstract  ComResult dealBusiness(List<DTO> obj,E importTask);


    /**
     * 子类可以重写excel解析逻辑
     * @return
     */
    protected abstract  List importYouself(E importTask) throws Exception;


    /**
     * 不满足需求，子类覆写
     * 1，如果是验证，则可以抛异常，外面捕获，返回comResult
     * 2, 修改task 对象，可以 super()后获取到返回值，再进行修改返回
     * @param obj
     */
    protected E modifyAndCheckObj(JSONObject obj) throws Exception{

        Integer loginid = obj.getInteger("hh-loginid");
        Integer companyId = obj.getInteger("hh-companyId");
        String url = obj.getString("url");
        Integer itType = obj.getInteger("itType");


        if (itType == null || url == null || loginid == null || companyId == null)
            throw new IllegalArgumentException(RetCode.RetNullPara_msg);


        try( InputStream temp = new URL(obj.getString("url")).openStream()){
        }catch (Exception e){ throw new IllegalArgumentException(RetCode.P_S_F_S_WJLJBZQ); }


        // 设置已知的一些值

        /*Integer titleRows = obj.getInteger("titleRows")!=null?obj.getInteger("titleRows"):1;
        Integer headerRows = obj.getInteger("headerRows")!=null?obj.getInteger("headerRows"):0;
        obj.put("titleRows", titleRows);
        obj.put("headerRows", headerRows);
*/

        Class<E> clazz = getClazz();
        E e = clazz.newInstance();


        return (E)e.setItType(itType)
                .setItState(1)
                .setItParm(obj.toJSONString())
                .setItOssUrl(obj.getString("url"))
                .setItUserId(obj.getInteger("hh-companyId"))
                .setItOptId(obj.getInteger("hh-loginid"));
    }



    @Override
    public ComResult addTask(JSONObject obj) {

            /** 子类校验 **/
            E sysTask;
            try {
                sysTask = modifyAndCheckObj(obj);
            }catch (Exception e){ return error(-99, e.getMessage()); }


            /** 如果有相同的任务，提示当前任务正在执行中 **/
            List<E> a =sysImportTaskService.list(new QueryWrapper<E>().setEntity(sysTask));
            if(a.size()>0) {
                return error(-99, "已有正在处理的上传操作，请稍后重试");
            }

            sysTask.setItStartTime(DateUtil.getNowTimeStr());
            sysImportTaskService.save(sysTask);
            return success(new JSONObject(){{ put("flag", sysTask.getItId());}});
    }


    /**
     * 执行入表操作
     * 1、查询任务
     * 2、子类解析excel逻辑->默认解析excel逻辑
     * 2、子类执行业务逻辑，不要忘记修改SysImportTask表的记录状态
     * 3、返回子类处理结果
     * @param itId
     * @return
     */
    @Override
    @Async
    @Transactional(rollbackFor = Exception.class)
    public ComResult excuteTask(int itId, Class<? extends DTO> pojoClass) {
        E importTask = sysImportTaskService.getById(itId);
        if (importTask != null && importTask.getItId() > 0 && importTask.getItState() == 1) {
            /** 优先执行子类的转换逻辑，如果子类没有实现，则执行默认的转换逻辑 **/
            List list;
            try {
                list  = importYouself(importTask);
            }catch (Exception e){
                /** 如果解析异常或者解析出0行数据，修改任务表状态 **/
                importTask.setItState(2);
                importTask.setItResult("excel解析异常，数据为空");
                sysImportTaskService.updateById(importTask);
                return error(-99, "excel解析异常，数据为空");
            }

            if(list == null || list.size() <= 0 ){
                /** 从任务表中获取参数 **/
                String prams = importTask.getItParm();
                JSONObject jsonObject1 = JSONObject.parseObject(prams);
                Integer titleRows = jsonObject1.getInteger("titleRows");
                Integer headerRows = jsonObject1.getInteger("headerRows");

                list = importOssExcel(importTask.getItOssUrl(), titleRows, headerRows, pojoClass);

                if(list == null || list.size() <= 0){
                    /** 如果解析异常或者解析出0行数据，修改任务表状态 **/
                    importTask.setItState(2).setItResult("excel解析异常，数据为空");
                    sysImportTaskService.updateById(importTask);
                    return error(-99, "excel解析异常，数据为空");
                }
            }
            return dealBusiness(list,importTask);
        }else{
            throw new RuntimeException("导入任务"+importTask.getItId()+"不存在,或已经处理");
        }
    }

    /**
     * 文件转list的默认方法方法
     * @param ossUrl
     * @param titleRows
     * @param headerRows
     * @param pojoClass
     * @return
     */
    public List importOssExcel(String ossUrl, Integer titleRows, Integer headerRows, Class<? extends DTO> pojoClass){
        if (StringUtils.isBlank(ossUrl)) {
            return null;
        }
        ImportParams params = new ImportParams();
        params.setTitleRows(titleRows);
        params.setHeadRows(headerRows);
//        params.setNeedVerfiy(true);
        params.setKeyIndex(0);
        List list = null;
        try {
            list = ExcelImportUtil.importExcel(new URL(ossUrl).openStream(), pojoClass, params);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }
}
